/**	
*	Drawing an infinite open book : 
	le livre Y
*/

import ij.ImagePlus;
import ij.plugin.PlugIn;
import ij.process.ColorProcessor;
import ij.process.ImageProcessor;

import java.awt.Color;
import java.awt.Polygon;
import java.io.PrintStream;

import java.util.Iterator;
import java.util.Random;
import java.util.TreeSet; 

public class LivreY2_ extends ImagePlus implements PlugIn {
	private TreeSet<Double> page=new TreeSet<Double>();
	private boolean windows=true; 
	private PrintStream output; 
	private Random gene=new Random();
	private int ind;
	
	private void addpages(int level){
		if(level<3){ 
			Double t[]=new Double[page.size()]; 
			Iterator<Double> curs=page.iterator();
			int index=0; 
			while(curs.hasNext()){
				t[index]=(Double)curs.next();	
				index++;
			}
			System.out.println(index+" "+t.length+" "+t[0]+" "+t[1]);
			int limite; 		
			if(level==0) limite=t.length-1; else limite=t.length-2; 
			for(int i=0;i<limite;i++){// inserer les pages entre les pages precedentes
				double a=t[i]; 
				double b=t[i+1]; 
				double cst=(a+b)/2; 
				double factor=(b-a)/4; // debug
				double coef=0.5; 
				for(int j=0;j<10;j++){ // debug 50
					page.add(cst-factor*coef);
					coef=coef/2; 
				}
			}
			addpages(level+1);
		}
	}
	

	public void run(String arg) {
		ImageProcessor primeIP = new ColorProcessor(2000, 2000);
		int R=850; 
		int r=20; 
		int xb=700,xa=1200,yb=1500,ya=1000; 
		int abscisses[]={xa,xb,xb,xa}; 
		int ordonnees[]={ya,yb,yb-R,ya-R};
		Polygon pl;
		
		try{
			if(!windows)
			output=new PrintStream("/tmp/pages.txt");
			else
				output=new PrintStream("F:/Povray/pages.txt");
			}
			catch(Exception e){System.out.println("Probleme 1 "+e); System.exit(0);}
		
		
		
		// Construction de l'ensemble
		page.add(0.0); 
		page.add(1.0);  
		addpages(0);
		
		Iterator<Double> curs=page.iterator();
		while(curs.hasNext())
			System.out.println(curs.next()); 
		
		float red=1.0f; 
		float green=1.0f;
		float blue=1.0f;
		
		
		Polygon background=new Polygon(new int[]{0,0,2000,2000},new int[]{0,2000,2000,0},4);
		primeIP.setColor(new Color(0.9f,0.9f,0.82f));
		 
		primeIP.fillPolygon(background);
		
		primeIP.setLineWidth(5);
		
		
		
		
		double limite=Math.atan(-(xa-xb+0.0)/(ya-yb+0.0));
		/* Illusion de perspective : concerne uniquement l'angle de la 
		 * partie basse du livre
		 */
		double theta=Math.PI/8;
		/* Controler l'aspect ouvert du livre */
		double ouverture=Math.PI/7;
		/* controle de la perspective */
		double coefP=0.72; 
		// Pages de gauche
		double alphaDebut=-Math.PI/2+theta+ouverture;
		
		System.out.println("---------------------->"+alphaDebut); 
		double alphaFin=Math.PI/2+theta;
		double alphaCoef=alphaFin-alphaDebut; 	
		// Largeur de la couverture depassant 
		int epsilon=15; 
		
		double alpha=alphaDebut; 
		// Deuxieme de couverture
		abscisses[0]=(int)(xa+r*Math.sin(alpha)); 
		abscisses[1]=(int)(xb+(r+epsilon)*Math.sin(alpha)); 
		abscisses[2]=(int)(xb+(R+r+2*epsilon)*Math.sin(alpha)); 
		abscisses[3]=(int)(xa+(R+r+epsilon)*Math.sin(alpha)*coefP); 
		ordonnees[0]=(int)(ya-r*Math.cos(alpha)); 
		ordonnees[1]=(int)(yb-(r-epsilon)*Math.cos(alpha)); 
		ordonnees[2]=(int)(yb-(R+r+0.8*epsilon)*Math.cos(alpha)); 
		ordonnees[3]=(int)(ya-(R+r+epsilon)*Math.cos(alpha)*coefP);
		
		pl=new Polygon(abscisses,ordonnees,4);
		
		primeIP.setColor(new Color(0.6f,0.04f,0.04f)); 
		primeIP.fillPolygon(pl);
		
		// Charger les valeurs dans un tableau
		Double t[]=new Double[page.size()]; 
		curs=page.iterator();
		int index=0; 
		double coef=-1.25; 
		while(curs.hasNext()){
			t[index]=(Double)curs.next();
			t[index]=t[index]*(coef*t[index]+(1-coef)); 
			index++;
		}
		System.out.println("----------------------->"+t.length); 
		// pages de gauche
		
		index=0; 
		
		alpha=alphaDebut+t[index]*alphaCoef; 
		while(alpha<limite){
			abscisses[0]=(int)(xa+r*Math.sin(alpha)); 
			abscisses[1]=(int)(xb+r*Math.sin(alpha)); 
			abscisses[2]=(int)(xb+(R+r)*Math.sin(alpha)); 
			abscisses[3]=(int)(xa+(R+r)*Math.sin(alpha)*coefP); 
			ordonnees[0]=(int)(ya-r*Math.cos(alpha)); 
			ordonnees[1]=(int)(yb-r*Math.cos(alpha)); 
			ordonnees[2]=(int)(yb-(R+r)*Math.cos(alpha)); 
			ordonnees[3]=(int)(ya-(R+r)*Math.cos(alpha)*coefP);
			
			pl=new Polygon(abscisses,ordonnees,4);
			primeIP.setColor(Color.DARK_GRAY); 
			primeIP.drawPolygon(pl); 
			primeIP.setColor(new Color(red,green,blue));
			ind=1+gene.nextInt(9); 
			//output.println("object{pageR"+ind+"  rotate "+alpha/Math.PI*180+"*x}");
			output.println("object{pageR  rotate "+alpha/Math.PI*180+"*x}");
			primeIP.fillPolygon(pl);
			index++; 
			alpha=alphaDebut+t[index]*alphaCoef; 
			if(index%1000==0) System.out.println("------------->"+index); 
			}
		
		// Pages de droite
		
		
		alpha=Math.PI/2+theta; 
		
		// Troisieme de couverture
		abscisses[0]=(int)(xa+r*Math.sin(alpha)); 
		abscisses[1]=(int)(xb+(r-epsilon)*Math.sin(alpha)); 
		abscisses[2]=(int)(xb+(R+r+2*epsilon)*Math.sin(alpha)); 
		abscisses[3]=(int)(xa+(R+r+epsilon)*Math.sin(alpha)*coefP); 
		ordonnees[0]=(int)(ya-r*Math.cos(alpha)); 
		ordonnees[1]=(int)(yb-(r+epsilon)*Math.cos(alpha)); 
		ordonnees[2]=(int)(yb-(R+r+4*epsilon)*Math.cos(alpha)); 
		ordonnees[3]=(int)(ya-(R+r+epsilon)*Math.cos(alpha)*coefP);
		
		pl=new Polygon(abscisses,ordonnees,4);
	
		primeIP.setColor(new Color(0.6f,0.04f,0.04f)); 
		primeIP.fillPolygon(pl);
		
		
		
		index=t.length-1; 
		alpha=alphaDebut+t[index]*alphaCoef; 
		while(alpha>limite){
			abscisses[0]=(int)(xa+r*Math.sin(alpha)); 
			abscisses[1]=(int)(xb+r*Math.sin(alpha)); 
			abscisses[2]=(int)(xb+(R+r)*Math.sin(alpha)); 
			abscisses[3]=(int)(xa+(R+r)*Math.sin(alpha)*coefP); 
			ordonnees[0]=(int)(ya-r*Math.cos(alpha)); 
			ordonnees[1]=(int)(yb-r*Math.cos(alpha)); 
			ordonnees[2]=(int)(yb-(R+r)*Math.cos(alpha)); 
			ordonnees[3]=(int)(ya-(R+r)*Math.cos(alpha)*coefP);
			
			pl=new Polygon(abscisses,ordonnees,4);
			primeIP.setColor(Color.DARK_GRAY); 
			primeIP.drawPolygon(pl); 
			primeIP.setColor(new Color(red,green,blue)); 
		    ind=1+gene.nextInt(9); 
			output.println("object{page"+ind+"  rotate "+alpha/Math.PI*180+"*x}"); 
			primeIP.fillPolygon(pl);
			index--; 
			alpha=alphaDebut+t[index]*alphaCoef; 
			if(index%1000==0) System.out.println(index); 
			}
		
		
		
		
		// Tranche avant gauche
		alpha=alphaDebut;
		
		abscisses[0]=(int)(xb+(r+epsilon)*Math.sin(alpha)); 
		abscisses[1]=(int)(xb+(R+r+2*epsilon)*Math.sin(alpha)); 
		abscisses[2]=abscisses[1]-15;
		abscisses[3]=abscisses[0]-15;	 
		ordonnees[0]=(int)(yb-(r-epsilon)*Math.cos(alpha)); 
		ordonnees[1]=(int)(yb-(R+r+0.8*epsilon)*Math.cos(alpha)); 
		ordonnees[2]=ordonnees[1]+15;
		ordonnees[3]=ordonnees[0]+15;
		
		pl=new Polygon(abscisses,ordonnees,4);
		primeIP.setColor(new Color(0.12f,0.02f,0.22f)); 
		primeIP.fillPolygon(pl);
		
		// Tranche avant droite	
		
		alpha=alphaFin; 
		 
		abscisses[0]=(int)(xb+(r-epsilon)*Math.sin(alpha)); 
		abscisses[1]=(int)(xb+(R+r+2*epsilon)*Math.sin(alpha)); 
		abscisses[2]=abscisses[1]-8;
		abscisses[3]=abscisses[0]-8;
 
		ordonnees[0]=(int)(yb-(r+epsilon)*Math.cos(alpha)); 
		ordonnees[1]=(int)(yb-(R+r+4*epsilon)*Math.cos(alpha)); 
		ordonnees[2]=ordonnees[1]+15;
		ordonnees[3]=ordonnees[0]+15;
		
		pl=new Polygon(abscisses,ordonnees,4);
		
		primeIP.setColor(new Color(0.12f,0.02f,0.22f)); 
	  
		primeIP.fillPolygon(pl);
		setProcessor("Verifying", primeIP);
		show();
		System.out.println("Casse-toi, j'ai fini");
	}

	

}
